#pragma once

#include <brpc/channel.h>
#include <brpc/naming_service.h>
#include <brpc/server_node.h>

#include <log.h>
#include <string>
#include <vector>
#include <regex>
#include "etcd.hpp"


namespace lyt {
    class EtcdNamingService : public brpc::NamingService {
    public:
        int RunNamingService(const char *service_name, brpc::NamingServiceActions *actions) override;
        // 返回false，代表运行在内部线程中，
        bool RunNamingServiceReturnsQuickly() override;
        NamingService *New() const override;
        // 销毁任务
        void Destroy() override;
        ~EtcdNamingService() override;

    private:
        // 添加服务的回调函数
        void AddServer(brpc::NamingServiceActions *actions, const std::string &host);
        // 删除服务的回调函数
        void RemoveServer(brpc::NamingServiceActions *actions, const std::string &host);

    private:
        std::vector<brpc::ServerNode> node;
        lyt::Discovery discovery;
    };

} // namespace ltx



namespace lyt {

    int EtcdNamingService::RunNamingService(const char *service_name, brpc::NamingServiceActions *actions) {
        // 设置true的状态
        // 匹配服务器发现地址和发现路径
        // 应该出现的字符串应该是 etcd://127.0.0.1:8080/user/login
        // std::regex re("([09.:]+)(.*)");
        // 会为每个channel创建新的EtcdNamingService对象
        // loginfo("EtcdNamingService :  {}", (size_t)this);
        std::regex re("^([^/]+)(.*)$");
        std::smatch sm;
        std::string name = service_name;
        if (std::regex_match(name, sm, re) == false) {
            return 1;
        }
        // 设置服务发现的地址和路径，以及事件更新的回调函数，启动服务监听
        discovery.setHost(sm[1].str())
            .setBaseDir(sm[2].str())
            .setUpdateCallback([this, actions](const std::string &host) { AddServer(actions, host); })
            .setRemoveCallback([this, actions](const std::string &host) { RemoveServer(actions, host); })
            .start();
        return 0;
    }
    // 返回false，代表运行在内部线程中，
    bool EtcdNamingService::RunNamingServiceReturnsQuickly() {
        return true;
    }

    brpc::NamingService *EtcdNamingService::New() const {
        return new EtcdNamingService();
    }
    // 销毁任务
    void EtcdNamingService::Destroy() {
    }

    EtcdNamingService::~EtcdNamingService() {
    }

    // 添加服务的回调函数,，actions用于管理和操作节点列表（比如ResetServers、AddServers()、RemoveServers）
    void EtcdNamingService::AddServer(brpc::NamingServiceActions *actions, const std::string &host) {
        butil::EndPoint ep;
        butil::str2endpoint(host.c_str(), &ep);
        infolog << "add service : " << host; 
        node.push_back(brpc::ServerNode(ep, host));
        actions->ResetServers(node);
    }
    // 删除服务的回调函数
    void EtcdNamingService::RemoveServer(brpc::NamingServiceActions *actions, const std::string &host) {
        for (auto it = node.begin(); it != node.end(); ++it) {
            if (it->tag == host) {
                node.erase(it);
            }
        }
        actions->ResetServers(node);
    }
    static std::string get_host(const std::string &addr) {
        //  http://127.0.0.1:2379
        //  127.0.0.1:2379
        // return 127.0.0.1:2379
        std::regex re(R"((?:http://)?((?:\d{1,3}\.){3}\d{1,3}:\d+))");
        std::smatch match;
        if (!std::regex_match(addr, match, re)) {
            return "";
        }
        return match[1].str();
    }
    static std::shared_ptr<brpc::Channel> build_etcd(const std::string &etcd_host, const std::string &path, int timeout = -1,
                                                     const std::string &load_balance = "rr") {
        std::shared_ptr<brpc::Channel> channel = std::make_shared<brpc::Channel>();
        brpc::ChannelOptions options;
        options.protocol = "baidu_std"; // 或者使用的其他协议
        options.timeout_ms = timeout;
        // "etcd://127.0.0.1:2379/user"
        std::string host = "etcd://";
        host += get_host(etcd_host);
        host += path;
        int ret = channel->Init(host.c_str(), load_balance.c_str(), &options);
        if (ret != 0) {
            channel.reset();
        }
        return channel;
    };

} // namespace ltx
